home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol194 / kermasm.arc / MSYIBM.ASM < prev   
Encoding:
Assembly Source File  |  1985-11-14  |  34.6 KB  |  1,322 lines

  1.  
  2.     title term
  3.  
  4. ; edit history:
  5. ;
  6. ; [v2.28]
  7. ; Don't scroll in inverse video lines (again).
  8. ; Backspace in column 0 backs up a line in wrap mode (from Greg Small,
  9. ;    UC Berkeley)
  10. ; Ansi set graphics rendition support (suggested by Greg Small, UC Berkeley)
  11. ; escape sequences of the form esc [ p1;p2;...;pn m where pi is
  12. ; one of 0,1,4,5,7 for normal, high-intensity, underline, blink,
  13. ; and reverse, respectively.
  14. ; JD May 1985
  15.  
  16. ; [v2.27]
  17. ; Fixed destructive tab problem (received from many people)
  18. ; Fixed insert/delete line problem when at bottom/top of screen.
  19. ; Newlines never scroll in inverse video lines
  20. ; Implemented cursor save/restore (from Univ. Md.)
  21. ; "Echo" status on mode corrected.
  22. ; JD, 6 December 1984
  23.  
  24.     public    term, gss, lclyini    ; entry points
  25.     include    msdefs.h
  26.  
  27. ; some character definitions
  28.  
  29. chesc    equ    27
  30. bel    equ    7
  31.  
  32. print_out equ    05h            ; dos function to print to printer
  33. pbout    equ    02h            ; dos function to print a character
  34. prscan    equ    72h            ; print-screen scan code...
  35. upscan    equ    49h            ; up page
  36. dnscan    equ    51h            ; down page
  37. ctlup    equ    84h            ; ctl-up page
  38. ctldn    equ    76h            ; ctl-down page
  39. homscn    equ    47h            ; home screen
  40. endscn    equ    4fh            ; end of screen
  41. screen    equ    10h            ; bios screen call
  42. kb    equ    16h            ; keyboard interrupt
  43. alt_shift equ    8H            ; alt shift key down
  44. ctl_shift equ    4H            ; ctl key down
  45. left_shift equ    2H            ; left shift key down
  46. right_shift equ    1H            ; right shift key down
  47.  
  48. timer    equ    40h            ; timer port
  49. bel_prt    equ    61h            ; speaker control
  50.  
  51. crt_status equ    3dah            ; crt status port
  52. disp_enb   equ    8            ; display enable bit
  53.  
  54. uparr    equ    48h            ; scan codes for arrow keys
  55. dnarr    equ    50h
  56. lftarr    equ    4bh
  57. rgtarr    equ    4dh
  58.  
  59.  
  60. modfrm    struc                ; format of mode line
  61.     db    'Esc chr: '
  62. m_echr    db    2 dup (?)
  63.     db    ', Port: '
  64. m_prt    db    1 dup (?)
  65.     db    ', Speed: '
  66. m_baud    db    4 dup (?)
  67.     db    ', Parity: '
  68. m_par    db    4 dup (?)
  69.     db    ', Echo: '
  70. m_echo    db    3 dup (?)
  71.     db    ', Type '
  72. m_hlp    db    2 dup (?)
  73.     db    '? for Help'
  74. modfrm    ends
  75.  
  76. datas    segment    public 'datas'
  77. waste    db    100h dup (?)        ;*** need this junk because assembler
  78.                     ;*** generates non-relocatable offsets
  79.                     ;*** for things like 
  80.                     ;*** "sub di,offset foo"
  81.                     ;*** if offset foo < 100H
  82. ; stuff for screen routines
  83. flags    db    ?            ; status flags...
  84. flags1    db    0            ; internal flags.
  85. prtscr    equ    80h            ; print screen pressed
  86. inited    equ    08h            ; been here before...
  87. wrapped    equ    04h            ; on if wrapped on last char...
  88. cursor    dw    ?
  89. esc_ch    db    ?
  90. argadr    dw    ?            ; address of arg blk
  91. ckeys    db    0,prscan,dnscan,upscan,endscn,homscn,ctlup,ctldn
  92.     db    uparr,dnarr,lftarr,rgtarr
  93. lckeys    equ    $-ckeys
  94. ; ckacts must parallel ckeys above...
  95. ckacts    dw    trnbrk,trnprs,dnwpg,upwpg,endwnd,homwnd,upwind,dnwind
  96.     dw    trnupw,trndnw,trnlfw,trnrgw
  97.  
  98. uptrn    db    esc,'A'
  99. dntrn    db    esc,'B'
  100. rgtrn    db    esc,'C'
  101. lftrn    db    esc,'D'
  102.  
  103. spctab    db    chesc,cr,lf,bs,tab,bel
  104. lspctab    equ    $-spctab
  105. spcjmp    dw    outesc,outcr,outlf,outbs,outtab,outbel    ; must match spctab
  106. esctab    db    'YABCDEFGHIJKLM'
  107.     db    'NOZ@[pq<vw'
  108.     db    'jkxy'
  109. lesctab    equ    $-esctab
  110. ; escjmp must parallel esctab above
  111. escjmp    dw    movcur,curup,curdwn,currt,outbs,clrscr,outign,outign,curhom
  112.     dw    revind,clreow,clreol,inslin,dellin,delchr,noins
  113.     dw    vtident,entins,doansi
  114.     dw    invvid,nrmvid,outign,dowrap,nowrap
  115.     dw    savecur,restcur,setmode,clrmode
  116. vtidstr    db    chesc,'/K'
  117. lvtidst    equ    $-vtidstr
  118. coord    dw    ?
  119. insmod    db    ?
  120. wcoord    dw    ?
  121. ttstate    dw    outtt0
  122. curattr    db    ?            ; current attribute
  123. ansarg    db    10 dup (?)        ; ansi argument values
  124. ansargl    equ    $-ansarg        ; length of table
  125. ansidx    dw    ?            ; index into table
  126. grtab    db    0,1,4,5,7        ; supported graphics renditions
  127. grtlen    equ    $-grtab
  128. ; the following two tables must parallel grtab
  129. attatab    db    07h,0ffh,0f8h,0ffh,088h    ; attribute bits to leave on
  130. attotab    db    07h,08h,01h,080h,070h    ; attributes to set
  131.  
  132. modesw    dw    ?
  133. igncnt    db    ?            ; # of chars to ignore
  134. beldiv    dw    2dch            ; 550 hz?
  135. crt_mode db    ?
  136. crt_cols db    ?
  137. crt_lins db    ?    
  138. low_rgt    dw    ?            ; lower right corner of window
  139. ; key redefinitions
  140. ktrntab    dw    ?            ; address of translation table
  141. krpltab    dw    ?            ; address of replacement table
  142. tmptab    db    0eh,3bh            ; scan code for bs, f1
  143. ktlen    dw    ?
  144. modbuf    modfrm    <>            ; mode line buffer
  145. ; routine to call for captured output
  146. captrtn    dw    ?
  147. oldcur    dw    0            ; save'd cursor position
  148. ; some static data for mode line
  149. unkbaud    db    'Unk '            ; must be 4 chars...
  150. baudn    db    '45.5'
  151.     db    '  50'
  152.     db    '  75'
  153.     db    ' 110'
  154.     db    ' 135'
  155.     db    ' 150'
  156.     db    ' 300'
  157.     db    ' 600'
  158.     db    '1200'
  159.     db    '1800'
  160.     db    '2000'
  161.     db    '2400'
  162.     db    '4800'
  163.     db    '9600'
  164.     db    '19.2'
  165.     db    '38.4'
  166. baudnsiz  equ    16            ; # of baud rates known (tbl size / 4)
  167. parnams    db    'Even'
  168.     db    'Mark'
  169.     db    'None'
  170.     db    'Odd '            ; must be 4 chars
  171.     db    'Spc '
  172. offmsg    db    'Off'
  173. onmsg    db    'On '
  174. lclmsg    db    'Lcl'
  175. remmsg    db    'Rem'
  176. ; storage for multi-window stuff
  177. swidth    equ    80
  178. slen    equ    24
  179. npgs    equ    5            ; # of pages on each side
  180. bsize    equ    swidth*slen*npgs*2
  181. scrsav    dw    ?
  182.  
  183.  
  184. ; circular buffer.  To work properly, the buffer size should be an exact
  185. ; multiple of swidth*2
  186. cbuf    struc
  187. pp    dw    ?            ; place ptr in buffer
  188. bend    dw    ?            ; end of buffer
  189. orig    dw    ?            ; buffer origin
  190. lcnt    dw    0            ; # of lines in buffer.
  191. cbuf    ends
  192.  
  193. tlbuf    dw    ?            ; db    swidth*2 dup (?)
  194. blbuf    dw    ?            ; db    swidth*2 dup (?)
  195. twnd    cbuf    <>
  196. bwnd    cbuf    <>
  197. portno    db    ?
  198. prton    db    'Printer: on'
  199. prtnlen    equ    $-prton
  200. prtoff    db    'Printer: off'
  201. prtflen    equ    $-prtoff
  202. lincur    dw    ?
  203. datas    ends
  204.  
  205. code    segment    public            ; code segment
  206.     extrn    prtchr:near,outchr:near,sendbr:near,malloc:near
  207.     assume    cs:code,ds:datas,es:datas
  208.  
  209. ; do initialization local to this module...
  210. lclyini    proc    near
  211.     mov    ax,swidth*slen*2
  212.     call    malloc
  213.     mov    scrsav,ax        ; place to save screens
  214.     mov    ax,swidth*2
  215.     call    malloc
  216.     mov    tlbuf,ax
  217.     mov    ax,swidth*2
  218.     call    malloc
  219.     mov    blbuf,ax        ; top and bottom temp line buffers
  220.     mov    ax,bsize
  221.     call    malloc
  222.     mov    twnd.pp,ax
  223.     mov    twnd.orig,ax
  224.     add    ax,bsize-1
  225.     mov    twnd.bend,ax
  226.     mov    ax,bsize
  227.     call    malloc
  228.     mov    bwnd.pp,ax
  229.     mov    bwnd.orig,ax
  230.     add    ax,bsize-1
  231.     mov    bwnd.bend,ax
  232.     ret
  233. lclyini    endp
  234.  
  235. scrini    proc    near            ; init screen stuff
  236.     mov    ah,15            ; read video state...
  237.     int    screen
  238.     mov    crt_mode,al        ; save crt mode
  239.     cmp    ah,crt_cols        ; is real # of cols < passed?
  240.     jge    scrin1            ; no
  241.     mov    crt_cols,ah        ; yes, save # of cols
  242. scrin1:    mov    dl,crt_cols        ; # of cols again
  243.     mov    dh,crt_lins        ; and # of rows
  244.     dec    dl
  245.     dec    dh
  246.     mov    low_rgt,dx        ; save away window address
  247.     mov    insmod,0        ; not in insert mode
  248.     mov    dx,cursor        ; assume old cursor
  249.     test    flags1,inited        ; have we been here before?
  250.     jnz    scrin4            ; yes, use old cursor
  251.     mov    curattr,07        ; else set nice screen attribute
  252.     mov    ttstate,offset outtt0    ; normal screen state
  253.     mov    ah,3            ; figure out where cursor is
  254.     xor    bh,bh            ; page 0
  255.     int    screen            ; read cursor position
  256.     mov    lincur,cx        ; save line (?) cursor value
  257.     cmp    dh,crt_lins        ; past logical end of screen?
  258.     jb    scrin2            ; no, keep going
  259.     mov    dh,byte ptr low_rgt+1    ; yes, just use lower right corner
  260. scrin2:    cmp    dl,crt_cols        ; maybe past right margin
  261.     jb    scrin3            ; no, use the way it is
  262.     mov    dl,byte ptr low_rgt
  263. scrin3:    mov    cursor,dx        ; init cursor
  264. scrin4:    mov    ah,2
  265.     xor    bh,bh
  266.     int    screen            ; set cursor in case it moved
  267.     ret
  268. scrini    endp
  269.  
  270. argini    proc    near            ; read passed arguments
  271.     mov    bx,argadr        ; base of argument block
  272.     mov    al,[bx].flgs        ; get flags
  273.     and    al,capt+emheath+havtt+trnctl+lclecho+modoff+lnwrap
  274.     mov    flags,al        ; mask for allowable and save
  275.     and    flags1,not (prtscr)    ; these are allowable
  276.                     ; (others remain).
  277.     mov    al,[bx].prt
  278.     cmp    al,portno        ; using same port?
  279.     je    argin1            ; yes, go on
  280.     and    flags1,not inited    ; else re-init stuff
  281. argin1:    mov    portno,al        ; update port number
  282.     mov    al,[bx].cols
  283.     mov    crt_cols,al
  284.     mov    al,[bx].rows
  285.     mov    crt_lins,al        ; init # of rows and cols
  286.     mov    ax,[bx].captr
  287.     mov    captrtn,ax        ; buffer capture routine
  288.     mov    ax,[bx].belld
  289.     mov    beldiv,ax        ; bell divisor
  290.     mov    ax,[bx].klen
  291.     mov    ktlen,ax        ; length of key redef tbl
  292.     mov    ax,[bx].ktab
  293.     mov    ktrntab,ax        ; save key translation table
  294.     mov    ax,[bx].krpl
  295.     mov    krpltab,ax
  296.     mov    al,[bx].escc
  297.     mov    esc_ch,al
  298.     ret                ; that's it
  299. argini    endp
  300.  
  301. modlin    proc    near            ; turn on mode line
  302.     mov    al,esc_ch
  303.     mov    modbuf.m_echr,' '    ; first char is initial space
  304.     mov    modbuf.m_hlp,' '    ; goes here too.
  305.     cmp    al,32            ; printable?
  306.     jnb    modl1            ; yes, keep going
  307.     add    al,40h            ; made printable
  308.     mov    modbuf.m_echr,'¬'    ; note control char
  309.     mov    modbuf.m_hlp,'¬'
  310. modl1:    mov    modbuf.m_echr+1,al    ; fill in character
  311.     mov    modbuf.m_hlp+1,al
  312.     mov    bx,argadr        ; get argument block
  313.     mov    al,[bx].baudb        ; get baud bits
  314.     mov    si,offset unkbaud    ; assume unknown baud
  315.     cmp    al,baudnsiz        ; too big?
  316.     jnb    modl2            ; yes, use default
  317.     mov    cl,2            ; each is 4 bytes long
  318.     shl    al,cl
  319.     mov    ah,0
  320.     add    ax,offset baudn
  321.     mov    si,ax
  322. modl2:    mov    cx,size m_baud        ; length of baud space
  323.     mov    di,offset modbuf.m_baud
  324.     rep    movsb            ; copy in baud rate
  325.     mov    al,[bx].parity        ; get parity code
  326.     mov    cl,2            ; each is 4 bytes long...
  327.     shl    al,cl
  328.     mov    ah,0
  329.     add    ax,offset parnams    ; names of parity settings
  330.     mov    si,ax
  331.     mov    cx,4            ; each is 4 long
  332.     mov    di,offset modbuf.m_par
  333.     rep    movsb
  334.     mov    si,offset remmsg    ; Assume remote echoing.
  335.     test    flags,lclecho        ; Is remote side echoing?
  336.     jz    modl4            ; Yes, keep going
  337.     mov    si,offset lclmsg    ; Else it's local echoing. 
  338. modl4:    mov    cx,3            ; size of on/off
  339.     mov    di,offset modbuf.m_echo
  340.     rep    movsb
  341.     mov    al,'1'
  342.     cmp    portno,1        ; port 1?
  343.     je    modl5            ; yes, keep going
  344.     mov    al,'2'
  345. modl5:    mov    modbuf.m_prt,al        ; fill in port number
  346.     mov    cx,size modfrm        ; this is size of mode line
  347.     mov    si,offset modbuf    ; mode line image
  348. ; alternate entry to write an alternate mode line
  349. modwrt:    push    cx
  350.     push    si            ; save mode line and size
  351.     mov    cx,1800h        ; line 25...
  352.     mov    dx,184fh
  353.     mov    ax,600h            ; scroll to clear the line
  354.     mov    bh,70h            ; inverse video
  355.     int    screen
  356.     mov    dx,24 * 100h
  357.     mov    bh,0
  358.     mov    ah,2            ; set cursor position
  359.     int    screen
  360.     pop    si
  361.     pop    cx            ; restore these
  362. modl6:    lodsb                ; get a byte
  363.     mov    ah,14            ; write to terminal
  364.     mov    bh,0            ; page 0
  365.     int    screen
  366.     loop    modl6            ; write out entire mode line
  367.     mov    dx,cursor
  368.     mov    ah,2
  369.     mov    bh,0
  370.     int    screen            ; put cursor back where it belongs
  371.     ret                ; and return
  372. modlin    endp
  373.  
  374. clrmod    proc    near            ; clear mode line
  375.     mov    ax,600h            ; blank window
  376.     mov    cx,24 * 100h        ; beginning of window
  377.     mov    dx,24 * 100h + 79    ; end of window
  378.     mov    bh,07            ; nice attribute
  379.     int    screen            ; clear mode line
  380.     ret                ; and return
  381. clrmod    endp
  382.  
  383. term    proc    near            ; terminal emulator entry point
  384.  
  385.     mov    argadr,ax        ; save argument ptr
  386.     push    es            ; save caller's extra segment address
  387.     mov    ax,seg datas
  388.     mov    es,ax
  389.  
  390.     call    argini            ; init options from arg address
  391.  
  392.     call    scrini            ; init screen stuff
  393.  
  394.     test    flags1,inited        ; have we run yet?
  395.     jz    term1            ; no, forget this part
  396.     call    restscr            ; restore screen
  397. term1:    or    flags1,inited        ; remember we've run already.
  398.  
  399.     call    clrmod            ; empty mode line
  400.     test    flags,modoff        ; is mode line disabled?
  401.     jnz    lp            ; yes, skip it
  402.     call    modlin            ; turn on mode line
  403.  
  404. lp:    call    portchr            ; char at port?
  405.      jnc    chkinp            ; no, keep going
  406.     call    outtty            ; print on terminal
  407.  
  408. chkinp:    mov    ah,1
  409.     int    kb
  410.     jz    lp            ; nothing available...
  411.     xor    ah,ah
  412.     int    kb            ; get the char from the buffer
  413.     push    ax            ; save character temporarily
  414.     call    gss            ; get shift state into al
  415.     mov    bl,al            ; save shift state
  416.     pop    ax
  417.  
  418.     cmp    al,esc_ch        ; escape character?
  419.     je    quit            ; yes, stop here
  420.  
  421.     call    trnout            ; translate if nec., output to prt
  422.     jmp    chkinp            ; and keep going
  423.  
  424. quit:    call    clrmod            ; erase mode line
  425.     call    savescr            ; save screen
  426.  
  427.     mov    al,flags
  428.     mov    bx,argadr
  429.     mov    [bx].flgs,al        ; update flags in arg block
  430.     pop    es            ; restore segment register
  431.     ret                ; and return to caller
  432.  
  433. term    endp
  434.  
  435. ; get shift state into al.  We only care about shift, ctl, and alt keys.
  436. ; right shift is collapsed into left shift.
  437. gss    proc    near
  438.     mov    ah,2
  439.     int    kb            ; get current shift state
  440.     mov    bl,al            ; copy for a moment
  441.     and    bl,right_shift        ; mask out all but right shift
  442.     shl    bl,1            ; move right shift to left shift pos
  443.     or    al,bl            ; collapse shift bits
  444.     and    al,(left_shift + alt_shift + ctl_shift)
  445.     ret
  446. gss    endp
  447.  
  448. ; save the screen so we can restore it
  449. ; maybe save cursor also.
  450. savescr    proc    near
  451.     push    ds
  452.     mov    si,0
  453.     mov    di,scrsav        ; place to put screen
  454.     mov    cx,80*24        ; # of words on screen
  455.     call    scrseg
  456.     push    ax            ; save screen segment
  457.     call    scrwait            ; wait for screen to be ready
  458.     pop    ds            ; address screen
  459.     rep    movsw            ; save the screen
  460.     pop    ds            ; restore this
  461.     ret                ; and return
  462. savescr    endp
  463.  
  464. ; restore screen from scrsav buffer
  465. restscr    proc    near
  466.     push    es
  467.     mov    si,scrsav        ; source
  468.     mov    di,0
  469.     mov    cx,80*24
  470.     call    scrseg
  471.     mov    es,ax
  472.     call    scrwait
  473.     rep    movsw            ; restore it
  474.     pop    es
  475.     ret
  476. restscr    endp
  477.  
  478. ; send the character in al out to the serial port
  479. ; handle echoing also...
  480. outprt    proc    near
  481.     test    flags,lclecho        ; echoing?
  482.     jz    outpr1            ; no, forget it
  483.     push    ax            ; save char
  484.     call    outtty            ; print it
  485.     pop    ax            ; restore
  486. outpr1:    mov    ah,al            ; this is where outchr expects it
  487.     call    outchr            ; output to the port
  488.      nop
  489.      nop
  490.      nop                ; skip returns...
  491.     ret
  492. outprt    endp
  493.  
  494. ; returns with carry on if a character is available
  495.  
  496. portchr    proc    near
  497.     call    prtchr            ; character at port?
  498.      jmp    short portc1        ; yes, go handle
  499.     nop                ; skip return is stupid...
  500.     clc                ; no carry -> no character
  501.     ret                ; and return...
  502. portc1:    and    al,7fh            ; we don't worry about parity here
  503.     stc                ; have a character
  504.     ret                ; and return
  505. portchr    endp
  506.  
  507.  
  508. ; translate the scan code in ah according to the translate table
  509. ; given in ktrntab/krpltab, output to port.  If no translation,
  510. ; use ascii char in al. (should probably include shift state
  511. ; somewhere).  Shift state is in bl.
  512. trnout    proc    near
  513.     test    flags,havtt        ; translate table given?
  514.     jz    trnou3            ; no, just output character
  515.     push    ax            ; save original value
  516.     mov    al,ah            ; put scan code into ah
  517.     mov    ah,bl            ; shift state into top half.
  518.     mov    di,ktrntab        ; pick up translate tbl
  519.     mov    cx,ktlen        ; length of tbl
  520.     repne    scasw            ; look for our key
  521.     pop    ax            ; recover character
  522.     jne    trnou3            ; not found, forget it
  523.     sub    di,ktrntab        ; get index into tbl
  524.     sub    di,2            ; (minus 2 for pre-increment)
  525.     mov    bx,krpltab        ; get replacement table
  526.     mov    si,[bx][di]        ; and addr of replacement
  527.     mov    cl,[si]            ; get first byte (length)
  528.     xor    ch,ch            ; clear high-order byte
  529.     inc    si            ; point to translation string
  530. trnou2:    lodsb                ; get a byte
  531.     push    si
  532.     push    cx            ; save important registers
  533.     call    outprt            ; send to port
  534.     pop    cx
  535.     pop    si
  536.     loop    trnou2            ; send all chars
  537.     ret                ; and return
  538. trnou3:    cmp    ah,4eh            ;*** plus key thing?
  539.     je    trnmod            ; yes, go toggle mode line
  540.     cmp    al,0            ; is it a special code?
  541.     jne    trnou4            ; no, don't do this
  542.     mov    al,ah            ; get scan code
  543.     mov    cx,lckeys        ; length of table
  544.     mov    di,offset ckeys        ; table address
  545.     repne    scasb
  546.     mov    al,0            ; ascii code was 0...
  547.     jne    trnou4            ; not found, keep going
  548.     sub    di,offset ckeys+1    ; get table offset
  549.     shl    di,1            ; shift for word offset
  550.     jmp    ckacts[di]        ; jump to appropriate routine
  551. trnou4:    call    outprt            ; just output single char
  552.     ret                ; and return
  553.  
  554. trnmod:    test    flags,modoff        ; mode line already off?
  555.     jnz    trnm1            ; yes, go turn on
  556.     call    clrmod            ; no, clear mode line here
  557.     or    flags,modoff        ; turn on flag
  558.     ret                ; and return
  559. trnm1:    call    modlin            ; turn on mode line
  560.     and    flags,not modoff    ; clear flag
  561.     ret                ; and return
  562.  
  563. trnbrk:    mov    ah,dconio
  564.     mov    dl,0ffH
  565.     int    dos            ; read the bogus ¬C DOS gets.
  566.     call    sendbr
  567.     ret
  568. trnprs:    xor    flags1,prtscr        ; flip the flag
  569.     and    flags,not modoff    ; turn on mode line
  570.     mov    si,offset prton
  571.     mov    cx,prtnlen
  572.     test    flags1,prtscr        ; did it go on?
  573.     jnz    trnpr1            ; yes, say so
  574.     mov    si,offset prtoff
  575.     mov    cx,prtflen
  576. trnpr1:    call    modwrt            ; write into mode line
  577.     ret                ; and return
  578.  
  579. ; common entry for arrow keys
  580. trnarr:    mov    cx,2            ; length is always 2
  581.     jmp    trnou2            ; go send definition
  582.  
  583. trnupw:    mov    si,offset uptrn
  584.     jmp    trnarr
  585.  
  586. trndnw:    mov    si,offset dntrn
  587.     jmp    trnarr
  588.  
  589. trnlfw:    mov    si,offset lftrn
  590.     jmp    trnarr
  591.  
  592. trnrgw:    mov    si,offset rgtrn
  593.     jmp    trnarr
  594.  
  595. trnout    endp
  596.  
  597. ; move viewing window up (screen moves down).
  598. ; alternate entry upwin2 doesn't beep if invalid.
  599. upwind    proc    near
  600.     mov    ax,tlbuf    ; place to put line temporarily
  601.     mov    bx,offset twnd ; where to get lines from
  602.     call    getcirc        ; try to get a line
  603.     jnc    upwin3        ; have a line, go show it
  604.     call    outbel        ; else ring bel
  605.     ret            ; and return
  606. upwin2:    mov    ax,tlbuf
  607.     mov    bx,offset twnd
  608.     call    getcirc
  609.     jnc    upwin3
  610.     ret            ; this just rets if no line avail.
  611. upwin3:    mov    ax,blbuf    ; place for bottom line
  612.     call    getbot        ; fetch bottom line
  613.     mov    ax,blbuf
  614.     mov    bx,offset bwnd
  615.     call    putcirc        ; save in circular buffer
  616.     mov    ax,701h        ; scroll down one line
  617.     xor    cx,cx        ; from top
  618.     mov    dx,low_rgt    ; to bottom
  619.     mov    bh,07        ; normal attributes
  620.     int    screen        ; scroll it down
  621.     mov    di,0        ; offset for destination
  622.     mov    si,tlbuf    ; where to get line from
  623.     mov    cx,swidth    ; length of line
  624.     push    es
  625.     call    scrseg
  626.     push    ax
  627.     call    scrwait
  628.     pop    es
  629.     rep    movsw        ; copy the line in
  630.     pop    es        ; restore this
  631.     ret            ; and return
  632. upwind    endp
  633.  
  634.  
  635. ; move viewing window down a line (screen scrolls up)
  636. ; entry dwin2 does same w/out checking to see if scroll is legal
  637. dnwind    proc    near
  638.     mov    ax,blbuf    ; place to put line temporarily
  639.     mov    bx,offset bwnd ; where to get lines from
  640.     call    getcirc        ; try to get a line
  641.     jnc    dnwin3        ; have a line, go show it
  642.     call    outbel        ; else ring bel
  643.     ret            ; and return
  644. dnwin2:    mov    ax,blbuf
  645.     mov    bx,offset bwnd
  646.     call    getcirc
  647.     jnc    dnwin3
  648.     ret            ; this just rets if no line avail.
  649. dnwin3:    call    scrprep        ; save top line
  650.     mov    ax,601h        ; scroll up one line
  651.     xor    cx,cx        ; from top
  652.     mov    dx,low_rgt    ; to bottom
  653.     mov    bh,07        ; normal attribute
  654.     int    screen        ; scroll it down
  655.     mov    dx,low_rgt
  656.     mov    dl,0        ; get addr of last line
  657.     call    scrloc
  658.     mov    di,ax        ; this is offset in dest
  659.     mov    si,blbuf    ; where to get line from
  660.     mov    cx,swidth    ; length of line
  661.     push    es
  662.     call    scrseg
  663.     push    ax
  664.     call    scrwait
  665.     pop    es
  666.     rep    movsw        ; copy the line in
  667.     pop    es        ; restore this
  668.     ret            ; and return
  669. dnwind    endp
  670.  
  671. ; move viewing window down as much as possible...
  672. endwnd    proc    near
  673.     mov    cx,1000            ; large number of lines
  674.     jmp    dnwp1            ; and enter dwnpg
  675. endwnd    endp
  676.  
  677. ; scroll viewing window down (contents move up) crt_lins times...
  678. dnwpg    proc    near
  679.     mov    cl,crt_lins
  680.     mov    ch,0
  681. dnwp1:    push    cx            ; save this
  682.     call    dnwin2
  683.     pop    cx
  684.     loop    dnwp1
  685.     ret                ; and return
  686. dnwpg    endp
  687.  
  688. ; home viewing window
  689. homwnd    proc    near
  690.     mov    cx,1000            ; large # of lines
  691.     jmp    upwp1            ; join upwpg
  692. homwnd    endp
  693.  
  694. ; scroll viewing window up (screen moves down) a page
  695. upwpg    proc    near
  696.     mov    cl,crt_lins
  697.     mov    ch,0
  698. upwp1:    push    cx
  699.     call    upwin2
  700.     pop    cx
  701.     loop    upwp1
  702.     ret                ; and return
  703. upwpg    endp
  704.  
  705. ; get the bottom line into the buffer pointed to by ax.
  706. getbot    proc    near
  707.     push    ds
  708.     mov    di,ax            ; save dest
  709.     mov    cx,swidth
  710.     mov    dx,low_rgt
  711.     mov    dl,0
  712.     call    scrloc
  713.     mov    si,ax
  714.     call    scrseg
  715.     push    ax
  716.     call    scrwait
  717.     pop    ds
  718.     rep    movsw
  719.     pop    ds
  720.     ret
  721. getbot    endp
  722.  
  723. ; put a line into the circular buffer.  Pass the buffer structure
  724. ; in bx, the pointer to the line in ax.
  725. putcirc    proc    near
  726.     push    si
  727.     push    di
  728.     push    cx
  729.     push    dx
  730.     mov    di,[bx].pp        ; pick up buffer ptr
  731.     add    di,2*swidth        ; increment to next avail slot
  732.     cmp    di,[bx].bend        ; past end?
  733.     jb    putci1            ; no, leave alone
  734.     mov    di,[bx].orig        ; else start at beginning
  735. putci1:    mov    [bx].pp,di        ; update ptr
  736.     mov    si,ax            ; this is source
  737.     mov    cx,swidth
  738.     rep    movsw            ; copy into buffer
  739.     cmp    [bx].lcnt,npgs*slen    ; can we increment it?
  740.     jae    putci2            ; no, keep going
  741.     inc    [bx].lcnt        ; else count this line
  742. putci2:    pop    dx
  743.     pop    cx
  744.     pop    di
  745.     pop    si            ; restore registers
  746.     ret
  747. putcirc    endp
  748.  
  749. ; get a line from the circular buffer, removing it from the buffer.
  750. ; returns with carry on if the buffer is empty.
  751. ; pass the buffer structure in bx, the buffer to copy the line into
  752. ; in ax.
  753. getcirc    proc    near
  754.     push    si
  755.     push    di
  756.     push    cx
  757.     push    dx
  758.     cmp    [bx].lcnt,0        ; any lines in buffer?
  759.     jne    getci1            ; yes, ok to take one out.
  760.     stc                ; else set carry
  761.     jmp    short getcir3        ; and return
  762. getci1:    mov    si,[bx].pp        ; this is source
  763.     mov    di,ax            ; this is dest
  764.     mov    cx,swidth        ; # of chars to copy
  765.     rep    movsw
  766.     mov    si,[bx].pp        ; get ptr again
  767.     sub    si,2*swidth        ; move back
  768.     cmp    si,[bx].orig        ; compare to origin
  769.     jae    getcir2            ; still in range, continue
  770.     mov    si,[bx].bend        ; else use end of buffer
  771.     sub    si,2*swidth-1        ; minus length of a piece
  772. getcir2:mov    [bx].pp,si        ; update ptr
  773.     dec    [bx].lcnt        ; decrement # of lines in buffer
  774.     clc                ; make sure no carry
  775. getcir3:pop    dx
  776.     pop    cx
  777.     pop    di
  778.     pop    si
  779.     ret
  780. getcirc    endp
  781.  
  782. ; call before scrolling to save top line...
  783. scrprep    proc    near
  784.     push    ds
  785.     mov    si,0            ; offset of top line
  786.     mov    cx,swidth        ; length of line
  787.     mov    di,tlbuf        ; place to put line temporarily
  788.     call    scrseg
  789.     push    ax
  790.     call    scrwait
  791.     pop    ds
  792.     rep    movsw            ; copy the line
  793.     pop    ds            ; restore this
  794.     mov    ax,tlbuf
  795.     mov    bx,offset twnd        ; this is where it goes
  796.     call    putcirc            ; put into buffer
  797.     ret                ; and return
  798. scrprep    endp
  799.  
  800.  
  801. ; put the character in al to the screen
  802. outtty    proc    near
  803.     test    flags,capt        ; capturing output?
  804.     jz    outnoc            ; no, forget this part
  805.     push    ax            ; save char
  806.     call    captrtn            ; give it captured character
  807.     pop    ax            ; restore character and keep going
  808.  
  809. outnoc:    test    flags1,prtscr        ; should we be printing?
  810.     jz    outnop            ; no, keep going
  811.     push    ax
  812.     mov    ah,print_out
  813.     mov    dl,al            ; put character here for dos...
  814.     int    dos
  815.     pop    ax
  816.  
  817. outnop:    test    flags,emheath        ; emulating heath?
  818.     jnz    outnop1            ; yup, go do something smart
  819.     mov    dl,al
  820.     mov    ah,pbout
  821.     int    dos            ; else let dos print char
  822.     ret                ; and return
  823.  
  824. outnop1:mov    dx,cursor        ; these may need cursor...
  825.     jmp    ttstate            ; jump according to current state
  826.  
  827. outtt0:
  828.     cmp    al,32            ; special character?
  829.     jb    outtt1            ; yes, handle specially...
  830.  
  831.     cmp    insmod,0        ; in insert mode?
  832.     je    outnrm            ; no, output normal
  833.     push    ax            ; save character
  834.     call    inschr            ; insert a character
  835.     pop    ax
  836. outnrm:    xor    bh,bh            ; current page
  837.     mov    cx,1            ; only one char
  838.     mov    bl,curattr        ; with current attribute
  839.     mov    ah,9
  840.     int    screen            ; put onto screen
  841.     mov    dx,cursor        ; get cursor pos
  842. currt:    inc    dl            ; bump col
  843.     cmp    dl,crt_cols        ; see if in range
  844.     jb    setcur            ; in range, go set cursor
  845.     test    flags,lnwrap        ; in wrap mode?
  846.     jz    outign            ; no, just return w/out updating cursor
  847. wrap:    xor    dl,dl
  848.     inc    dh            ; handle wrap
  849.     or    flags1,wrapped        ; remember we wrapped
  850.     jmp    short setc0        ; and don't turn off flag
  851. setcur:    and    flags1,not wrapped    ; if moving cursor, turn off wrap flag
  852. setc0:    cmp    dh,crt_lins
  853.     jb    setc1            ; not off end, keep going
  854.     push    dx            ; save row/col
  855.     call    scrprep            ; save top line in window buf
  856.     mov    ax,0601h        ; scroll up one line
  857.     xor    cx,cx            ; from 0,0
  858.     mov    dx,low_rgt        ; to 24,80
  859.     mov    bh,7            ; nice attribute
  860.     int    screen            ; do the scroll
  861.     pop    dx
  862.     mov    dh,crt_lins        ; go to bottom line again...
  863.     dec    dh
  864. setc1:    xor    bh,bh            ; page is 0
  865.     mov    cursor,dx        ; save cursor pos
  866.     mov    ah,2
  867.     int    screen            ; set cursor
  868. outign:    ret                ; and return
  869. ; special character (in al)
  870. outtt1:    mov    di,offset spctab    ; special char table
  871.     mov    cx,lspctab        ; length of tbl
  872.     repne    scasb            ; look for char in tbl
  873.     jz    outtt2            ; found, go do something with it
  874.     test    flags,trnctl        ; are we allowed to print carets?
  875.     jz    outign            ; no, just ignore it.
  876.     push    ax            ; save char
  877.     mov    al,'¬'
  878.     call    outtty            ; print caret
  879.     pop    ax
  880.     add    al,'A'-1        ; make printable
  881.     jmp    outtty            ; print, then return
  882.  
  883. outtt2:    mov    dx,cursor        ; might need cursor pos
  884.     sub    di,offset spctab+1    ; get index of char
  885.     shl    di,1            ; double for word offset
  886.     jmp    spcjmp[di]        ; and go handle
  887.  
  888. ; special char routines.  cursor is in dx, char in al
  889.  
  890. outlf:    test    flags1,wrapped        ; just wrapped?
  891.     jz    outlf1            ; no, proceed normally
  892.     and    flags1,not wrapped    ; else turn off wrap flag
  893.     ret                ; and skip this lf
  894. outlf1:    inc    dh            ; bump row
  895.     jmp    setcur
  896.  
  897. outcr:    test    flags1,wrapped        ; just wrapped?
  898.     jz    outcr1            ; no, continue
  899.     ret                ; yes, already in col 0
  900. outcr1:    xor    dl,dl            ; set col to 0
  901.     jmp    setcur
  902.  
  903. outbs:    or    dl,dl
  904.     jg    outbs1            ; > col 0, just back up
  905.     test    flags,lnwrap        ; auto wrap on?
  906.     jz    outbs2            ; no, stay at left margin
  907.     or    dh,dh            ; at top of screen?
  908.     jz    outbs2            ; yes, stay where we are
  909.     mov    dl,crt_cols        ; get rightmost column
  910.     dec    dh            ; go up a row
  911. outbs1:    dec    dl            ; back up a column
  912. outbs2:    jmp    setcur            ; go set cursor
  913.  
  914. outtab:    mov    dl,byte ptr cursor    ; get initial column
  915.     add    dl,8            ; tab is at most 8 columns
  916.     and    dl,not 111b        ; round down to a multiple of 8
  917.     cmp    dl,crt_cols        ; out of range?
  918.     jae    outta1            ; yes, skip it
  919.     jmp    setcur            ; else set it
  920. outta1:    test    flags,lnwrap        ; in wrap mode?
  921.     jnz    outta2            ; yes, wrap to next line
  922.     mov    dl,byte ptr low_rgt    ; else just move to right margin
  923.     jmp    setcur
  924. outta2:    jmp    wrap
  925.     
  926. ; stolen from bios
  927. outbel:    mov    al,10110110b        ; timer initialization
  928.     out    timer+3,al
  929.     mov    ax,beldiv        ; bel divisor
  930.     out    timer+2,al
  931.     mov    al,ah
  932.     out    timer+2,al        ; output divisor
  933.     in    al,bel_prt
  934.     mov    ah,al            ; remember original value
  935.     or    al,3            ; turn speaker on
  936.     out    bel_prt,al
  937.     mov    cx,8888h
  938. outbe1:    loop    outbe1            ; wait a while
  939.     mov    al,ah
  940.     out    bel_prt,al        ; turn bell off
  941.     ret                ; and return
  942.  
  943. outesc:    mov    ttstate,offset escseq    ; expect escape sequence.
  944.     ret                ; and return
  945.  
  946. ; escape-char handling routines
  947. escseq:    mov    ttstate,offset outtt0    ; put state back to normal
  948.     mov    di,offset esctab    ; escape char tbl
  949.     mov    cx,lesctab        ; length of tbl
  950.     repne    scasb            ; look for it in tbl
  951.     jz    escsq1            ; found, go use it
  952.     jmp    outnoc            ; not there, print it (already logged)
  953. escsq1:    sub    di,offset esctab+1    ; get offset into tbl
  954.     shl    di,1            ; convert to word offset
  955.     jmp    escjmp[di]        ; and go dispatch on it
  956.  
  957. ; escape dispatch routines
  958. revind:    cmp    dh,0
  959.     jle    revin1
  960.     dec    dh            ; back up a row
  961.     jmp    setcur            ; and go set cursor
  962. revin1:    push    dx            ; save cursor pos
  963.     mov    ax,701h            ; scroll down one line
  964.     xor    cx,cx            ; from top
  965.     mov    dx,low_rgt        ; to bottom
  966.     mov    bh,07            ; normal attributes
  967.     int    screen            ; scroll it down
  968.     pop    dx            ; restore cursor.
  969.     mov    dh,0            ; set row back to 0
  970.     jmp    setcur
  971.  
  972. curup:    cmp    dh,0            ; w/in range?
  973.     jle    curu1            ; no, skip this
  974.     dec    dh            ; else back up
  975. curu1:    jmp    setcur            ; and go set position
  976.  
  977. curdwn:    inc    dh
  978.     jmp    setcur            ; increment row (setcur can scroll!)
  979.  
  980. ; currt is above
  981.  
  982. clrscr:    call    curhom            ; go home cursor
  983.     jmp    clreow            ; then clear to end of window
  984.  
  985. curhom:    xor    dx,dx            ; move to 0,0
  986.     jmp    setcur
  987.  
  988. clreow:    cmp    dl,0            ; at beginning of line?
  989.     jz    clrw1            ; yes, skip this part...
  990.     push    dx            ; remember cursor pos
  991.     call    clreol            ; clear to end of this line
  992.     pop    dx
  993.     inc    dh            ; bump row
  994.     xor    dl,dl            ; start from col 0
  995. clrw1:    cmp    dh,crt_lins        ; last line on screen
  996.     jnb    clrw2            ; if not in range, forget it
  997.     mov    ax,700h            ; clear whole window
  998.     mov    cx,dx            ; this is beginning
  999.     mov    dx,low_rgt
  1000.     mov    bh,07            ; normal attribute
  1001.     int    screen            ; go clear it
  1002. clrw2:    ret                ; and return
  1003.  
  1004. clreol:    push    es
  1005.     mov    cl,crt_cols        ; last col + 1
  1006.     sub    cl,dl            ; this is # of chars to move
  1007.     xor    ch,ch
  1008.     jcxz    clrl1
  1009.     call    scrloc            ; compute screen location (to ax)
  1010.     mov    di,ax
  1011.     call    scrseg
  1012.     mov    es,ax            ; address screen segment
  1013.     call    scrwait            ; wait for retrace
  1014.     mov    ah,07            ; current attribute
  1015.     mov    al,' '            ; fill char
  1016.     rep    stosw            ; fill line with spaces
  1017. clrl1:    pop    es
  1018.     ret                ; and return
  1019.  
  1020. inslin:    mov    al,1            ; scroll one line
  1021. ; alternate entry if inserting more then one line
  1022. inslin1:mov    ch,dh            ; start at current row
  1023.     xor    cl,cl            ; column 0
  1024.     mov    dx,low_rgt
  1025.     mov    ah,7h            ; scroll down.
  1026.     mov    bh,07            ; normal attribute
  1027.     cmp    ch,dh            ; moving last line down?
  1028.     jne    insli2            ; no, keep going
  1029.     mov    al,0            ; yes, just clear it
  1030. insli2:    int    screen
  1031.     ret
  1032.  
  1033. dellin:    mov    al,1            ; scroll 1 line
  1034. ; alternate entry if deleting more than one line
  1035. dellin1:mov    ch,dh            ; start at current row
  1036.     xor    cl,cl            ; column 0
  1037.     mov    dx,low_rgt
  1038.     mov    ah,6h            ; scroll up.
  1039.     mov    bh,07            ; normal attribute
  1040.     cmp    ch,dh            ; deleting last line?
  1041.     jne    delli2            ; no, go on
  1042.     mov    al,0            ; yes, just blank it
  1043. delli2:    int    screen
  1044.     ret
  1045.  
  1046. delchr:    push    ds
  1047.     push    es
  1048.     pushf            ; these may get changed...
  1049.     mov    cl,crt_cols
  1050.     dec    cl
  1051.     sub    cl,dl        ; from what we're fiddling)
  1052.     xor    ch,ch
  1053.     jcxz    delch1        ; none to move, forget it
  1054.     call    scrloc        ; compute location
  1055.     mov    di,ax
  1056.     mov    si,ax
  1057.     add    si,2        ; source is next position over
  1058.     call    scrseg        ; pick up screen segment
  1059.     push    ax        ; put screen segment onto stack
  1060.     mov    es,ax        ; and in destination segment
  1061.     call    scrwait        ; wait for retrace
  1062.     pop    ds        ; address screen segment
  1063.     rep    movsw        ; delete it
  1064.     mov    byte ptr [di],' ' ; kill char at end of line
  1065. delch1:    popf
  1066.     pop    es
  1067.     pop    ds
  1068.     ret
  1069.  
  1070. inschr:    push    ds
  1071.     push    es        ; save these as well
  1072.     pushf            ; might as well save flags...
  1073.     mov    dx,cursor    ; this is place to do it
  1074.     mov    cl,crt_cols
  1075.     dec    cl
  1076. ;    mov    cl,79        ; this is last col to move, +1 for length
  1077.     sub    cl,dl        ; compute distance to end
  1078.     xor    ch,ch        ; clear top half of offset
  1079.     jcxz    insch1        ; nothing to move...
  1080.     mov    dl,crt_cols
  1081.     sub    dl,2        ; last col to move
  1082. ;    mov    dl,78        ; this is address of last col to move
  1083.     call    scrloc        ; compute pos
  1084.     mov    si,ax
  1085.     mov    di,ax
  1086.     add    di,2        ; destination is one byte over...
  1087.     std            ; remember to move us backwards
  1088.     call    scrseg        ; find screen segment
  1089.     mov    es,ax
  1090.     push    ax        ; save screen seg on stack
  1091.     call    scrwait        ; wait until save to write
  1092.     pop    ds        ; address screen segment
  1093.     rep    movsw        ; move each char and attribute
  1094. insch1:    popf
  1095.     pop    es
  1096.     pop    ds
  1097.     ret            ; and return
  1098.  
  1099. noins:    mov    insmod,0        ; turn off insert mode
  1100.     ret                ; and return
  1101.  
  1102. movcur:    mov    wcoord,2        ; want two coordinates...
  1103.     mov    ttstate,offset getcoord
  1104.     ret                ; and return
  1105.  
  1106. vtident: mov    si,offset vtidstr
  1107.     mov    cx,lvtidst
  1108. vtid1:    lodsb                ; get a byte from the string
  1109.     push    si            ; have to save from outprt
  1110.     push    cx
  1111.     call    outprt            ; send to serial port
  1112.     pop    cx
  1113.     pop    si
  1114.     loop    vtid1            ; go thru all chars
  1115.     ret                ; and return
  1116.  
  1117. entins:    mov    insmod,0ffh        ; enter insert mode...
  1118.     ret                ; and return
  1119.  
  1120. doansi:    mov    cx,ansargl        ; # of arg bytes
  1121.     mov    al,0
  1122.     mov    di,offset ansarg    ; point to arg list
  1123.     rep    stosb            ; clear it
  1124.     mov    ansidx,0        ; none seen yet
  1125.     mov    ttstate,offset getaarg    ; state is get ansi argument
  1126.     ret
  1127.  
  1128. getaarg:cmp    al,'0'
  1129.     jb    getaa1            ; in range for digit?
  1130.     cmp    al,'9'
  1131.     ja    getaa1
  1132.     sub    al,'0'            ; convert to binary
  1133.     mov    dl,al            ; tuck away
  1134.     mov    bx,ansidx
  1135.     mov    al,ansarg[bx]
  1136.     mov    dh,10
  1137.     mul    dh            ; shift sum
  1138.     add    al,dl            ; add in this digit (what about ovfl?)
  1139.     mov    ansarg[bx],al
  1140.     ret                ; and return
  1141.  
  1142. getaa1:    cmp    al,'?'            ; the dreaded question mark?
  1143.     jne    getaa2
  1144.     mov    ttstate,offset ignn    ; we ignore these...
  1145.     mov    igncnt,2        ; this is how many chars come after him
  1146.     ret
  1147.  
  1148. getaa2:    cmp    al,';'            ; argument separator?
  1149.     jne    getaa5            ; no, keep going
  1150.     inc    ansidx            ; yes, increment index
  1151.     cmp    ansidx,ansargl        ; is it too big?
  1152.     jb    getaa6            ; no, keep going
  1153. ;### this isn't good, but it beats having these parameters written
  1154. ; all over our data segment...
  1155.     mov    ansidx,1        ; yes, throw some away
  1156. getaa6:    ret                ; and return
  1157.  
  1158. getaa5:    mov    ttstate,offset outtt0    ; reset state
  1159.     mov    dx,cursor        ; this needs cursor position
  1160.     mov    bl,ansarg
  1161.     xchg    al,bl            ; put argument in nice place
  1162.     cmp    bl,'L'            ; insert line?
  1163.     jne    getaa3
  1164.     jmp    inslin1            ; and go do it
  1165.  
  1166. getaa3:    cmp    bl,'M'            ; maybe delete line?
  1167.     jne    getaa4
  1168.     jmp    dellin1
  1169.  
  1170. getaa4:    cmp    bl,'m'            ; maybe set graphic rendition
  1171.     jne    getaa7            ; no, keep going
  1172.     mov    cx,ansidx        ; argument index
  1173.     inc    cx            ; allow for 0 index origin...
  1174.     mov    si,offset ansarg
  1175.     call    setgrph            ; go set it all up
  1176. getaa7:    ret                ; ignore.
  1177.  
  1178.  
  1179. ; set graphic rendition... enter with si/ pointer to argument table,
  1180. ; cx/ length of table
  1181. setgrph:
  1182.     mov    ah,curattr        ; get current attributes
  1183.     jcxz    setgr3            ; empty table, stop here
  1184. setgr1:    lodsb                ; get a byte from the table
  1185.     push    cx
  1186.     mov    di,offset grtab        ; table of recognizable attributes
  1187.     mov    cx,grtlen        ; length of table
  1188.     repne    scasb            ; look for our char
  1189.     jne    setgr2            ; not found, keep going
  1190.     sub    di,offset grtab+1    ; get table index
  1191.     and    ah,attatab[di]        ; keep correct bits
  1192.     or    ah,attotab[di]        ; and turn on appropriate new bits
  1193. setgr2:    pop    cx            ; restore counter
  1194.     loop    setgr1            ; loop thru table
  1195. setgr3:    mov    curattr,ah        ; restore attributes
  1196.     ret                ; and return
  1197.  
  1198. invvid:    mov    curattr,70h        ; attribute for inverse video
  1199.     ret
  1200.  
  1201. nrmvid:    mov    curattr,07h        ; attribute for normal video
  1202.     ret
  1203.  
  1204. dowrap:    or    flags,lnwrap        ; turn on wrap mode
  1205.     ret                ; and return
  1206.  
  1207. nowrap:    and    flags,not lnwrap    ; turn off wrap mode
  1208.     ret                ; and return
  1209.  
  1210. ; get a coordinate.
  1211. getcoord:
  1212.     sub    al,32            ; coordinates offset by 32
  1213.     mov    si,wcoord
  1214.     dec    si
  1215.     mov    byte ptr coord[si],al    ; fill in appropriate coordinate
  1216.     mov    wcoord,si        ; update flag
  1217.     jnz    getco1            ; more needed, can't do anything yet
  1218.     mov    ttstate,offset outtt0    ; reset state
  1219.     mov    dx,coord        ; get coordinates
  1220.     jmp    setcur            ; and go jump there
  1221. getco1:    ret
  1222.  
  1223. ; ignore following igncnt characters
  1224. ignn:    dec    igncnt            ; decrement count
  1225.     jnz    ignn1
  1226.     mov    ttstate,offset outtt0    ; put state back to normal if done
  1227. ignn1:    ret
  1228.  
  1229. ; save cursor
  1230. savecur:
  1231.     mov    oldcur,dx
  1232.     ret
  1233.  
  1234. ; restore cursor
  1235. restcur:
  1236.     mov    dx,oldcur
  1237.     jmp    setcur
  1238.     
  1239. setmode:
  1240.     mov    modesw,offset setmo1
  1241.     mov    ttstate,offset getmod
  1242.     ret
  1243. ; al contains argument digit...
  1244. setmo1:
  1245.     cmp    al,4            ; set block mode?
  1246.     jne    setmo2            ; no, go on
  1247.     mov    cx,10ch            ; block cursor
  1248.     mov    ah,1            ; set cursor...
  1249.     int    screen
  1250. setmo2:    ret
  1251.  
  1252. clrmode:
  1253.     mov    modesw,offset clrmo1
  1254.     mov    ttstate,offset getmod
  1255.     ret
  1256. ; al contains argument digit
  1257. clrmo1:    cmp    al,4            ; is it set block mode?
  1258.     jne    clrmo2
  1259.     mov    cx,lincur
  1260.     mov    ah,1
  1261.     int    screen
  1262. clrmo2:    ret
  1263.  
  1264. ; get a single-digit mode argument
  1265. getmod:    mov    ttstate,offset outtt0    ; reset state
  1266.     cmp    al,'0'
  1267.     jb    getmo1            ; out of range
  1268.     cmp    al,'9'
  1269.     ja    getmo1
  1270.     sub    al,'0'            ; convert to numeric
  1271.     jmp    modesw            ; return to whoever wanted argument
  1272. getmo1:    ret                ; just ignore if out of range
  1273.  
  1274. outtty    endp
  1275.  
  1276. ; computes screen location to ax, given row and col in dx.
  1277. ; trashes ax,bx
  1278. scrloc    proc    near
  1279.     mov    al,dh        ; get row
  1280.     mov    bl,crt_cols    ;** row size
  1281.     mul    bl        ; multiply by row size
  1282.     xor    dh,dh        ; clear col
  1283.     add    ax,dx        ; this is current position
  1284.     sal    ax,1        ; double for attributes
  1285.     ret
  1286. scrloc    endp
  1287.  
  1288. ; puts current screen segment in ax
  1289. scrseg    proc    near
  1290.     mov    ax,0b000h        ; assume bw for now
  1291.     cmp    crt_mode,7        ; 7 is bw (***)
  1292.     je    scrse1
  1293.     mov    ax,0b800h        ; color card
  1294. scrse1:    ret
  1295. scrseg    endp
  1296.  
  1297. ; wait for retrace so can write to screen memory
  1298. scrwait    proc    near
  1299.     cmp    crt_mode,7        ; bw mode?
  1300.     je    scrwa3            ; yes, no waiting
  1301.     push    dx
  1302.     mov    dx,crt_status
  1303. scrwa1:    in    al,dx
  1304.     test    al,disp_enb        ; display enable?
  1305.     jnz    scrwa1            ; yes, keep waiting
  1306. scrwa2:    in    al,dx
  1307.     test    al,disp_enb        ; now wait for it to go off
  1308.     jz    scrwa2            ; so can have whole cycle
  1309.     pop    dx
  1310. scrwa3:    ret                ; that was easy...
  1311. scrwait    endp
  1312. code    ends
  1313.  
  1314. if1
  1315.     %out [End of pass 1]
  1316. else
  1317.     %out [End of assembly]
  1318. endif
  1319.  
  1320.     end
  1321.  
  1322.